/*
 * Copyright 2015, gRPC Authors All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mian.server;

import com.mian.annotation.RemoteService;
import io.grpc.BindableService;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.logging.Logger;

/**
 * Server that manages startup/shutdown of a {@code Greeter} server.
 */
@Component
public class GrpcServer implements ApplicationListener<ContextRefreshedEvent> {
  private static final Logger logger = Logger.getLogger(GrpcServer.class.getName());


  private Server server;

  private void start(Map<String, Object> serviceSet) throws Exception {
    /* The port on which the server should run */
    int port = 50051;

    ServerBuilder<?> serverBuilder = ServerBuilder.forPort(port);

    // todo 需要记录 key=具体的serviceImpl, value=host:port 到zk上，方便客户端引用servieImpl的时候，指定链接哪个server

    // key = serviceSet.get(key).getClass().getGenericSuperclass()
    //          --> com.mian.netty.demo.GreeterGrpc$GreeterImplBase  服务端可以获取到
    //          --> com.mian.netty.demo.GreeterGrpc$GreeterBlockingStub 客户端可以获取到
    for (String key : serviceSet.keySet()){
      serverBuilder.addService((BindableService) serviceSet.get(key));
    }
    server = serverBuilder.build().start();

    logger.info("Server started, listening on " + port);
    Runtime.getRuntime().addShutdownHook(new Thread() {
      @Override
      public void run() {
        // Use stderr here since the logger may have been reset by its JVM shutdown hook.
        System.err.println("*** shutting down gRPC server since JVM is shutting down");
        GrpcServer.this.stop();
        System.err.println("*** server shut down");
      }
    });
  }

  private void stop() {
    if (server != null) {
      server.shutdown();
    }
  }




  /**
   * Await termination on the main thread since the grpc library uses daemon threads.
   */
  private void blockUntilShutdown() throws InterruptedException {
    if (server != null) {
      server.awaitTermination();
    }
  }


  @Override
  public void onApplicationEvent(ContextRefreshedEvent event) {

    ApplicationContext applicationContext = event.getApplicationContext();
    Map<String, Object> serviceSet = applicationContext.getBeansWithAnnotation(RemoteService.class);
    try{
      final GrpcServer server = new GrpcServer();
      server.start(serviceSet);
      server.blockUntilShutdown();
    }catch (Exception e){
      e.printStackTrace();
    }
  }

}
